<template>
  <div class="notifications-view">
    <!-- 头部 -->
    <div class="header">
      <h1 class="title">消息中心</h1>
      <button 
        class="mark-all-read-btn" 
        @click="markAllAsRead"
        :disabled="isLoading || isRefreshingToken"
      >
        <span v-if="isRefreshingToken">刷新中...</span>
        <span v-else>全部标记已读</span>
      </button>
    </div>
    
    <!-- 标签栏 -->
    <div class="notification-tabs">
      <button 
        class="tab-btn"
        :class="{ 'active': activeTab === 'all' }"
        @click="setActiveTab('all')"
        :disabled="isLoading"
      >
        <BellIcon class="tab-icon" />
        <span>全部通知</span>
        <span v-if="unreadCount > 0" class="badge">{{ unreadCount }}</span>
      </button>
      <button 
        class="tab-btn"
        :class="{ 'active': activeTab === 'unread' }"
        @click="setActiveTab('unread')"
        :disabled="isLoading"
      >
        <MailWarningIcon class="tab-icon" />
        <span>未读通知</span>
        <span v-if="unreadCount > 0" class="badge">{{ unreadCount }}</span>
      </button>
      <button 
        class="tab-btn"
        :class="{ 'active': activeTab === 'likes' }"
        @click="setActiveTab('likes')"
        :disabled="isLoading"
      >
        <HeartIcon class="tab-icon" />
        <span>点赞</span>
      </button>
      <button 
        class="tab-btn"
        :class="{ 'active': activeTab === 'comments' }"
        @click="setActiveTab('comments')"
        :disabled="isLoading"
      >
        <MessageSquareIcon class="tab-icon" />
        <span>评论</span>
      </button>
      <button 
        class="tab-btn"
        :class="{ 'active': activeTab === 'follows' }"
        @click="setActiveTab('follows')"
        :disabled="isLoading"
      >
        <UserPlusIcon class="tab-icon" />
        <span>关注</span>
      </button>
      <button 
        class="tab-btn"
        :class="{ 'active': activeTab === 'chats' }"
        @click="navigateToChatList()"
        :disabled="isLoading"
      >
        <MessagesSquareIcon class="tab-icon" />
        <span>聊天</span>
        <span v-if="chatUnreadCount > 0" class="badge">{{ chatUnreadCount }}</span>
      </button>
    </div>
    
    <!-- 通知列表 -->
    <div class="notification-list">
      <div v-if="isLoading" class="loading-state">
        <div class="spinner"></div>
        <p>加载通知中...</p>
      </div>
      
      <div v-else-if="filteredNotifications.length > 0" class="notifications-container">
        <div 
          v-for="notification in filteredNotifications" 
          :key="notification.id"
          class="notification-item"
          :class="{ 'unread': !notification.read }"
          @click="handleNotificationClick(notification)"
        >
          <!-- 头像 -->
          <div class="notification-avatar">
            <img 
              :src="notification.relatedUser?.avatarUrl || '/default-avatar.png'" 
              alt="用户头像" 
              class="avatar"
              @error="(e) => handleImageError(e)"
              :data-has-handled="false"
            >
            <div class="notification-type-badge" :class="getTypeClass(notification.type)">
              <component :is="getTypeIcon(notification.type)" class="badge-icon" />
            </div>
          </div>
          
          <!-- 内容 -->
          <div class="notification-content">
            <div class="notification-header">
              <span class="username">{{ notification.relatedUser?.nickname || '未知用户' }}</span>
              <span class="time">{{ formatTime(notification.createdAt) }}</span>
            </div>
            
            <div class="notification-body">
              <p class="notification-text">{{ notification.content }}</p>
            </div>
            
            <!-- 操作按钮 -->
            <div class="notification-actions">
              <button 
                v-if="!notification.read" 
                class="mark-read-btn"
                @click.stop="markAsRead(notification.id)"
                :disabled="isRefreshingToken"
              >
                标记已读
              </button>
              <button 
                class="action-btn" 
                @click.stop="handleAction(notification)"
                :disabled="isRefreshingToken"
              >
                {{ getActionText(notification.type) }}
              </button>
            </div>
          </div>
        </div>
      </div>
      
      <div v-else class="empty-state">
        <div class="empty-icon">
          <BellIcon class="icon" />
        </div>
        <p class="empty-text">暂无通知</p>
        <p class="empty-subtext">当有人点赞、评论、关注你或发送消息时，通知会出现在这里</p>
      </div>
    </div>
    
    <!-- 加载更多 -->
    <div v-if="hasMore && !isLoading" class="load-more">
      <button 
        class="load-more-btn" 
        @click="loadMoreNotifications"
        :disabled="isRefreshingToken"
      >
        加载更多通知
      </button>
    </div>
    
    <!-- Token过期提示 -->
    <div v-if="showTokenExpiryWarning" class="token-expiry-warning">
      <div class="warning-content">
        <p>您的登录状态即将过期</p>
        <div class="warning-actions">
          <button class="refresh-btn" @click="refreshToken">刷新登录状态</button>
          <button class="ignore-btn" @click="showTokenExpiryWarning = false">忽略</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { 
  BellIcon, HeartIcon, MessageSquareIcon, 
  UserPlusIcon, MailWarningIcon, MessagesSquareIcon 
} from 'lucide-vue-next'
import { useAuthStore } from '@/store/auth'
import { useNotificationStore } from '@/store/notifications'
import { useChatStore } from '@/store/chat'

// 状态管理
const authStore = useAuthStore()
const notificationStore = useNotificationStore()
const chatStore = useChatStore()
const router = useRouter()

// 响应式数据
const activeTab = ref('all')
const isLoading = computed(() => notificationStore.isLoading)
const notifications = computed(() => notificationStore.notifications)
const hasMore = computed(() => notificationStore.hasMore)
const unreadCount = computed(() => notificationStore.unreadCount)
const chatUnreadCount = computed(() => chatStore.unreadCount)
const isRefreshingToken = ref(false)
const showTokenExpiryWarning = ref(false)
let tokenExpiryCheckTimer = null // 定时器（替换setInterval为setTimeout递归）

// 过滤通知（按标签）
const filteredNotifications = computed(() => {
  switch (activeTab.value) {
    case 'unread':
      return notifications.value.filter(n => !n.read)
    case 'likes':
      return notifications.value.filter(n => n.type === 'LIKE')
    case 'comments':
      return notifications.value.filter(n => n.type === 'COMMENT' || n.type === 'REPLY')
    case 'follows':
      return notifications.value.filter(n => n.type === 'FOLLOW')
    default:
      return notifications.value
  }
})

// 生命周期：初始化
onMounted(async () => {
  if (!authStore.isAuthenticated) {
    router.push('/login')
    return
  }
  
  // 启动Token过期检查（递归setTimeout避免累积）
  startTokenExpiryCheck()
  
  try {
    // 检查Token是否即将过期
    if (authStore.isTokenExpiringSoon()) {
      isRefreshingToken.value = true
      const refreshed = await authStore.refreshToken()
      if (!refreshed) {
        handleTokenExpired()
        return
      }
    }
    
    // 初始化WebSocket（单例）+ 加载数据
    notificationStore.initWebSocket()
    await Promise.all([
      notificationStore.fetchNotifications(),
      chatStore.fetchUnreadCount()
    ])
  } catch (error) {
    console.error('消息中心初始化失败:', error)
    if (error.response?.status === 401) {
      handleTokenExpired()
    }
  } finally {
    isRefreshingToken.value = false
  }
})

// 组件卸载前：清理定时器+WebSocket订阅
onBeforeUnmount(() => {
  clearTokenExpiryCheck()
  cancelWebSocketSubscription()
})

// 组件卸载：双重保险
onUnmounted(() => {
  clearTokenExpiryCheck()
  cancelWebSocketSubscription()
})

// 1. Token过期检查：递归setTimeout（避免setInterval累积）
const startTokenExpiryCheck = () => {
  const checkExpiry = () => {
    if (authStore.isTokenExpiringSoon()) {
      showTokenExpiryWarning.value = true
    }
    // 1分钟后再次检查
    tokenExpiryCheckTimer = setTimeout(checkExpiry, 60 * 1000)
  }
  checkExpiry() // 立即执行一次
}

// 清理Token检查定时器
const clearTokenExpiryCheck = () => {
  if (tokenExpiryCheckTimer) {
    clearTimeout(tokenExpiryCheckTimer)
    tokenExpiryCheckTimer = null
  }
}

// 2. 取消WebSocket订阅
const cancelWebSocketSubscription = () => {
  if (authStore.user?.id) {
    const channel = `/user/${authStore.user.id}/notifications`
    notificationStore.unsubscribeWebSocket(channel)
  }
}

// 3. 刷新Token
const refreshToken = async () => {
  isRefreshingToken.value = true
  try {
    const success = await authStore.refreshToken()
    if (success) {
      showTokenExpiryWarning.value = false
      // 重新加载数据
      await Promise.all([
        notificationStore.fetchNotifications(true),
        chatStore.fetchUnreadCount()
      ])
    } else {
      handleTokenExpired()
    }
  } catch (error) {
    console.error('刷新Token失败:', error)
    handleTokenExpired()
  } finally {
    isRefreshingToken.value = false
  }
}

// 4. 处理Token过期
const handleTokenExpired = () => {
  authStore.logout()
  router.push('/login')
}

// 5. 切换标签（加加载锁避免重复请求）
const setActiveTab = async (tab) => {
  if (isLoading.value || activeTab.value === tab) return
  activeTab.value = tab
  try {
    if (tab === 'unread') {
      await notificationStore.fetchUnreadNotifications()
    } else {
      await notificationStore.fetchNotifications(true)
    }
  } catch (error) {
    console.error('切换标签加载失败:', error)
    if (error.response?.status === 401) {
      handleTokenExpired()
    }
  }
}

// 6. 加载更多通知
const loadMoreNotifications = async () => {
  if (isLoading.value || !hasMore.value) return
  try {
    await notificationStore.fetchNotifications()
  } catch (error) {
    console.error('加载更多通知失败:', error)
    if (error.response?.status === 401) {
      handleTokenExpired()
    }
  }
}

// 7. 标记单个通知已读
const markAsRead = async (notificationId) => {
  if (isRefreshingToken.value) return
  try {
    await notificationStore.markAsRead(notificationId)
  } catch (error) {
    console.error('标记通知已读失败:', error)
    if (error.response?.status === 401) {
      handleTokenExpired()
    }
  }
}

// 8. 全部标记已读
const markAllAsRead = async () => {
  if (isLoading.value || isRefreshingToken.value || unreadCount.value === 0) return
  try {
    await notificationStore.markAllAsRead()
  } catch (error) {
    console.error('全部标记已读失败:', error)
    if (error.response?.status === 401) {
      handleTokenExpired()
    }
  }
}

// 9. 点击通知：标记已读+跳转
const handleNotificationClick = async (notification) => {
  if (isRefreshingToken.value) return
  try {
    if (!notification.read) {
      await markAsRead(notification.id)
    }
    handleAction(notification)
  } catch (error) {
    console.error('处理通知点击失败:', error)
    if (error.response?.status === 401) {
      handleTokenExpired()
    }
  }
}

// 10. 通知操作：跳转对应页面
const handleAction = (notification) => {
  const { type, targetId, sourceId } = notification
  switch (type) {
    case 'LIKE':
      router.push(`/notes/${targetId}`)
      break
    case 'COMMENT':
    case 'REPLY':
      router.push(`/notes/${targetId}?commentId=${sourceId}`)
      break
    case 'FOLLOW':
      router.push(`/users/${sourceId}`)
      break
    case 'CHAT':
      router.push(`/chats/${sourceId}`)
      break
    default:
      break
  }
}

// 11. 跳转到聊天列表
const navigateToChatList = () => {
  if (!isLoading.value) {
    router.push('/chats')
  }
}

// 12. 处理图片加载错误（防循环）
const handleImageError = (event) => {
  const img = event.target
  // 已处理过则跳过（避免循环）
  if (img.dataset.hasHandled === 'true') return
  
  // 默认头像也加载失败时，用内嵌SVG占位
  if (img.src.includes('default-avatar.png')) {
    img.src = ''
    img.dataset.hasHandled = 'true'
    img.removeEventListener('error', handleImageError)
    return
  }
  
  // 普通头像加载失败→替换为默认头像
  img.src = '/default-avatar.png'
  img.dataset.hasHandled = 'true'
}

// 13. 工具方法：通知类型样式
const getTypeClass = (type) => {
  return {
    'type-like': type === 'LIKE',
    'type-comment': type === 'COMMENT' || type === 'REPLY',
    'type-follow': type === 'FOLLOW',
    'type-chat': type === 'CHAT',
    'type-default': true
  }
}

// 14. 工具方法：通知类型图标
const getTypeIcon = (type) => {
  switch (type) {
    case 'LIKE': return HeartIcon
    case 'COMMENT': case 'REPLY': return MessageSquareIcon
    case 'FOLLOW': return UserPlusIcon
    case 'CHAT': return MessagesSquareIcon
    default: return BellIcon
  }
}

// 15. 工具方法：操作文字
const getActionText = (type) => {
  switch (type) {
    case 'LIKE': return '查看笔记'
    case 'COMMENT': case 'REPLY': return '查看评论'
    case 'FOLLOW': return '查看主页'
    case 'CHAT': return '查看消息'
    default: return '查看详情'
  }
}

// 16. 工具方法：时间格式化
const formatTime = (timestamp) => {
  if (!timestamp) return ''
  const now = new Date()
  const time = new Date(timestamp)
  const diff = now - time
  
  const minute = 60 * 1000
  const hour = 60 * minute
  const day = 24 * hour
  
  if (diff < minute) return '刚刚'
  if (diff < hour) return `${Math.floor(diff / minute)}分钟前`
  if (diff < day) return `${Math.floor(diff / hour)}小时前`
  if (diff < 7 * day) return `${Math.floor(diff / day)}天前`
  return time.toLocaleDateString()
}
</script>

<style scoped>
.notifications-view {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  background: white;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  position: relative;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 1px solid #f0f0f0;
}

.title {
  font-size: 24px;
  font-weight: 600;
  color: #333;
  margin: 0;
}

.mark-all-read-btn {
  padding: 8px 16px;
  background: #66D7D2;
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: 0 2px 6px rgba(102, 215, 210, 0.3);
  min-width: 120px;
}

.mark-all-read-btn:hover:not(:disabled) {
  background: #55c7c2;
  transform: translateY(-1px);
  box-shadow: 0 3px 8px rgba(102, 215, 210, 0.4);
}

.mark-all-read-btn:active:not(:disabled) {
  transform: translateY(0);
  box-shadow: 0 1px 4px rgba(102, 215, 210, 0.3);
}

.mark-all-read-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
  box-shadow: none;
}

.notification-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 1px solid #f0f0f0;
  overflow-x: auto;
}

.tab-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: #f5f5f5;
  border: none;
  border-radius: 20px;
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.2s;
}

.tab-btn.active {
  background: #66D7D2;
  color: white;
}

.tab-btn:hover:not(.active) {
  background: #e0e0e0;
}

.tab-icon {
  width: 18px;
  height: 18px;
}

.notification-list {
  min-height: 400px;
}

.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  color: #666;
}

.spinner {
  width: 32px;
  height: 32px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #66D7D2;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 16px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.notifications-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.notification-item {
  display: flex;
  padding: 16px;
  background: #fafafa;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
  border-left: 4px solid transparent;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.notification-item.unread {
  background: #f0f9ff;
  border-left-color: #66D7D2;
}

.notification-item:hover {
  background: #f5f5f5;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.notification-avatar {
  position: relative;
  margin-right: 16px;
  flex-shrink: 0;
}

.avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid #eee;
}

.notification-type-badge {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  border: 2px solid white;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.badge-icon {
  width: 14px;
  height: 14px;
}

.type-like { 
  background: linear-gradient(135deg, #ff6b6b, #ff4757);
  color: white;
}

.type-comment { 
  background: linear-gradient(135deg, #51cf66, #2ed573);
  color: white;
}

.type-follow { 
  background: linear-gradient(135deg, #4dabf7, #339af0);
  color: white;
}

.type-chat { 
  background: linear-gradient(135deg, #748ffc, #5c7cfa);
  color: white;
}

.type-system { 
  background: linear-gradient(135deg, #ff922b, #ffa502);
  color: white;
}

.type-default { 
  background: linear-gradient(135deg, #adb5bd, #868e96);
  color: white;
}

.notification-content {
  flex: 1;
  min-width: 0;
}

.notification-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.username {
  font-weight: 600;
  color: #333;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.time {
  font-size: 12px;
  color: #999;
  flex-shrink: 0;
  margin-left: 8px;
}

.notification-text {
  margin: 0 0 8px 0;
  color: #666;
  font-size: 14px;
  line-height: 1.4;
}

.notification-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.mark-read-btn, .action-btn {
  padding: 6px 12px;
  border: none;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s;
}

.mark-read-btn {
  background: #66D7D2;
  color: white;
  box-shadow: 0 1px 3px rgba(102, 215, 210, 0.2);
}

.mark-read-btn:hover:not(:disabled) {
  background: #55c7c2;
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(102, 215, 210, 0.3);
}

.action-btn {
  background: #e0e0e0;
  color: #666;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.action-btn:hover:not(:disabled) {
  background: #d0d0d0;
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
}

.mark-read-btn:disabled, .action-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  text-align: center;
}

.empty-icon {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: #f0f9ff;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 20px;
  box-shadow: 0 4px 12px rgba(102, 215, 210, 0.15);
}

.empty-icon .icon {
  width: 40px;
  height: 40px;
  color: #66D7D2;
}

.empty-text {
  font-size: 18px;
  color: #666;
  margin-bottom: 8px;
}

.empty-subtext {
  font-size: 14px;
  color: #999;
  margin: 0;
}

.load-more {
  display: flex;
  justify-content: center;
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid #f0f0f0;
}

.load-more-btn {
  padding: 10px 20px;
  background: #f5f5f5;
  border: none;
  border-radius: 6px;
  color: #666;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.load-more-btn:hover:not(:disabled) {
  background: #e0e0e0;
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
}

.load-more-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.token-expiry-warning {
  position: fixed;
  top: 20px;
  right: 20px;
  background: #fff9e6;
  border: 1px solid #ffd700;
  border-radius: 8px;
  padding: 15px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: 1000;
  animation: fadeIn 0.3s ease-in-out;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: translateY(0); }
}

.warning-content {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.warning-content p {
  margin: 0;
  font-size: 14px;
  color: #e67e22;
}

.warning-actions {
  display: flex;
  gap: 10px;
}

.refresh-btn, .ignore-btn {
  padding: 6px 12px;
  border: none;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s;
}

.refresh-btn {
  background: #66D7D2;
  color: white;
}

.ignore-btn {
  background: #e0e0e0;
  color: #666;
}

.refresh-btn:hover {
  background: #55c7c2;
}

.ignore-btn:hover {
  background: #d0d0d0;
}

.badge {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 6px;
  background: #ff4757;
  color: white;
  font-size: 12px;
  border-radius: 10px;
}

@media (max-width: 768px) {
  .notifications-view {
    padding: 16px;
    margin: 0;
    border-radius: 0;
  }
  
  .header {
    flex-direction: column;
    gap: 12px;
    align-items: flex-start;
  }
  
  .notification-tabs {
    gap: 4px;
  }
  
  .tab-btn {
    padding: 6px 12px;
    font-size: 13px;
  }
  
  .notification-item {
    padding: 12px;
  }
  
  .avatar {
    width: 40px;
    height: 40px;
  }
  
  .notification-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  
  .time {
    margin-left: 0;
  }
  
  .token-expiry-warning {
    top: 10px;
    right: 10px;
    left: 10px;
    width: calc(100% - 20px);
  }
}
</style>